﻿using System;
using System.Reflection;

namespace Useful.MVP2
{
    public abstract class BaseDetailPresenter<M, IV, IR> : BasePresenter<M, IV, IR>
        where M : BaseDetailModel, new()
        where IV : IDetailView
    {
        protected BaseDetailPresenter(IV view, IR repository, IPresenterImpl presenterImpl)
            : base(view, repository, presenterImpl)
        {
            View.CloseOKClicked += View_CloseOKClicked;
            View.CloseCancelClicked += View_CloseCancelClicked;
            View.ViewInited += View_ViewInited;
        }

        private void View_ViewInited(object sender, InitDetailViewEventArgs e)
        {
            try
            {
                OnViewInited(e);
            }
            catch (Exception ex)
            {
                HandleException(MethodBase.GetCurrentMethod().Name, ex);
            }
        }

        protected virtual void OnViewInited(InitDetailViewEventArgs e)
        {
            Repository = (IR)e.Repository;
            Model.AllowWrite = e.AllowWrite;
        }

        private void View_CloseCancelClicked(object sender, EventArgs e)
        {
            try
            {
                OnCloseCancelClicked();
            }
            catch (Exception ex)
            {
                HandleException(MethodBase.GetCurrentMethod().Name, ex);
            }
        }

        private void View_CloseOKClicked(object sender, EventArgs e)
        {
            try
            {
                OnCloseOKClicked();
            }
            catch (Exception ex)
            {
                HandleException(MethodBase.GetCurrentMethod().Name, ex);
            }
        }

        protected override void OnViewLoad()
        {
            View.EnableWrite = Model.AllowWrite;
        }

        protected override void OnViewClose()
        {
            Model.Dispose();
        }

        protected virtual void OnCloseOKClicked()
        {
            GetDataFromView();

            if (ValidateData() && Model.AllowWrite)
            {
                ShowWaiting(Repository, "Сохранение", () =>
                {
                    if (Model.InsertMode)
                        InsertData();
                    else
                        UpdateData();
                });

                View.IsOK = true;
                ShowWarring("OK");
            }
        }

        protected virtual void OnCloseCancelClicked()
        {
            GetDataFromView();

            if (HasChanges())
            {
                if (ShowQuestion("Данные изменены!\r\nВсё равно закрыть окно?"))
                    View.Close();
            }
            else
                View.Close();
        }

        protected abstract void GetDataFromView();
        protected abstract bool HasChanges();
        protected abstract bool ValidateData();
        protected abstract void InsertData();
        protected abstract void UpdateData();
    }
}
